/**
  ******************************************************************************
  * @file    Slib.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   该文件作为要保护的算法文件库，将其加载在flash固定区域
  *
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "sym32l010_hal_def.h"
#include "Slib.h"


/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/
#define SlibKeys    0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA    // SLIB区域的KEY值（由用户配置）
#define StartIdx    (0x7E)                                            // SLIB区域起始Page索引（由用户配置）
#define EndIdx      (0x7F)                                            // SLIB区域结束Page索引（由用户配置）
#define CTRL_KEY    0x49, 0x53, 0xA5, 0xA5                            // SLIB区域特定字符序列（用户不可更改）
#define CRCL        (0xEB)                                            // SLIB区域的CRC16_X25（由用户计算得到并填入）
#define CRCH        (0x72)


/******************************************************************************/
/* Global variable definitions (declared in header file with 'extern')        */
/******************************************************************************/

/******************************************************************************/
/* Local type definitions ('typedef')                                         */
/******************************************************************************/

/******************************************************************************/
/* Local function prototypes ('static')                                       */
/******************************************************************************/
void              Slib_Led_Blink(void)                                      __attribute__ ((section(".ARM.__at_0x0000FC00")));
void              Slib_Delay(uint32_t DlyCnt)                               __attribute__ ((section(".ARM.__at_0x0000FE00")));
uint32_t          Slib_GetValue(void)                                       __attribute__ ((section(".ARM.__at_0x0000FE40")));
uint32_t          Slib_ReadWord(uint32_t *Addr)                             __attribute__ ((section(".ARM.__at_0x0000FE80")));
uint32_t          Slib_WriteWord(uint32_t *Addr, uint32_t Value)            __attribute__ ((section(".ARM.__at_0x0000FEC0")));
uint8_t           Slib_ErasePage(uint32_t *pStartAddr, uint32_t *pEndAddr)  __attribute__ ((section(".ARM.__at_0x0000FF00")));

/******************************************************************************/
/* Local variable definitions ('static')                                      */
/******************************************************************************/
const uint32_t    Slib_UserValue     __attribute__ ((section(".ARM.__at_0x0000FF80"))) = 0x12345678;
const uint8_t     Slib_Record[]      __attribute__((section(".ARM.__AT_0x0000FFF0"))) =
{
    // SlibKey0~7
    SlibKeys,
    // StartIdx and EndIdx
    StartIdx & 0x7F, EndIdx & 0x7F,
    // Mcu Key
    CTRL_KEY,
    // CRC
    CRCL, CRCH
};

/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Function implementation - global ('extern') and local ('static')           */
/******************************************************************************/

/*******************************************************************************
 * @brief  Slib区函数，Led 闪烁
 * @param  None
 * @retval None
 */
void Slib_Led_Blink(void)
{
    SYM_SYSCTRL->AHBEN |= SYSCTRL_CR_KEY | SYSCTRL_AHBEN_GPIOA_Msk;

    SYM_GPIOA->ODR_f.PIN3 = 1;
    SYM_GPIOA->DIR_f.PIN3 = 0;
    SYM_GPIOA->ANALOG_f.PIN3 = 0;

    while (1)
    {
        SYM_GPIOA->TOG = bv3;
        Slib_Delay(80000);
    }
}


/*******************************************************************************
 * @brief  Slib区函数，Delay函数
 * @param  DlyCnt : Delay 的计数
 * @retval None
 */
void Slib_Delay(uint32_t DlyCnt)
{
    volatile uint32_t tmp32 = DlyCnt;
    while (tmp32)
    {
        tmp32--;
    }
}


/*******************************************************************************
 * @brief  Slib区函数，获取Slib区内静态常量
 * @param  None
 * @retval Slib_UserValue : Slib区内定义的静态常量
 */
uint32_t Slib_GetValue(void)
{
    return Slib_UserValue;
}


/*******************************************************************************
 * @brief  Slib区函数，从FLASH指定地址读取1个Word宽度的数据
 * @param  Addr : 指向FLASH目标地址的指针
 * @retval Word ：返回读取的数据
 * @note   注意 : Addr 传入地址应该32bit位宽对齐
 */
uint32_t Slib_ReadWord(uint32_t *Addr)
{
    SYM_FLASH->CR1 = FLASH_CR_KEY;
    return *Addr;
}


/*******************************************************************************
 * @brief  Slib区函数，向FLASH指定地址写入1个Word宽度的数据
 * @param  Addr  : 指向FLASH目标地址的指针
 * @param  Value : 写入的值
 * @retval Word  ：返回已经写入的数据
 * @note   注意  : Addr 传入地址应该32bit位宽对齐
 */
uint32_t Slib_WriteWord(uint32_t *Addr, uint32_t Value)
{
    uint32_t PageLockBak = SYM_FLASH->PAGELOCK;
    SYM_FLASH->PAGELOCK = FLASH_CR_KEY | 0xFFFF;
    SYM_FLASH->CR1      = FLASH_CR_KEY | 0x01;                        // write

    *Addr = Value;
    while (SYM_FLASH->ISR_f.BUSY) { ; }

    SYM_FLASH->PAGELOCK = FLASH_CR_KEY | PageLockBak;
    SYM_FLASH->CR1 = FLASH_CR_KEY;

    return *Addr;
}


/*******************************************************************************
 * @brief  Slib区函数，页擦
 * @param  pStartAddr  : 指向起始地址的指针
 * @param  pEndAddr    : 指向结束地址的指针
 * @retval State       ：返回状态，0 代表正常，非0代表出现错误
 * @note   注意        : 传入的起始与结束地址应该32bit位宽对齐
 */
uint8_t Slib_ErasePage(uint32_t *pStartAddr, uint32_t *pEndAddr)
{
    if (((uint32_t)pStartAddr > (uint32_t)pEndAddr) || ((uint32_t)pEndAddr > 0xFFFF)) // 检查操作地址
    {
        return HAL_ERROR;
    }

    uint32_t PageLockBak = SYM_FLASH->PAGELOCK;
    SYM_FLASH->PAGELOCK = FLASH_CR_KEY | 0xFFFF;
    SYM_FLASH->CR1      = FLASH_CR_KEY | 0x02;                        // sect erase

    uint32_t StartAddr = (uint32_t)pStartAddr / 512 * 512;            // 变成页面的起始地址
    uint32_t EndAddr   = (uint32_t)pEndAddr   / 512 * 512;            // 变成页面的起始地址

    SYM_FLASH->ICR = 0x00;                                            // Clear all int flag
    while (StartAddr <= EndAddr)
    {
        *((volatile uint8_t *)(StartAddr)) = 0x00;                    // Erase page
        while (SYM_FLASH->ISR & FLASH_ISR_BUSY_Msk) { ; }             // 等待操作完成
        StartAddr += 512;
    }

    SYM_FLASH->PAGELOCK = FLASH_CR_KEY | PageLockBak;
    SYM_FLASH->CR1 = FLASH_CR_KEY;

    return SYM_FLASH->ISR;
}


/*******************************************************************************
 ** EOF (not truncated)
 ******************************************************************************/
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END */
}
#endif /* USE_FULL_ASSERT */


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
